/** 
 * @file SuperGestor.java
 * 
 * Implementación del SuperGestor.
 * 
 * @author Ernesto Rivera
 * Modificado por lecarrera
 *
 * @date 2009-09-20
 */

package estadistec.logica;

import java.util.Hashtable;

import estadistec.logica.gestores.Gestor;
import estadistec.logica.LEscritorio;

import estadistec.logica.dependencias.IBuscarNodo;
import estadistec.logica.dependencias.Nodo;

import estadistec.logica.tabla.TipoTabla;

import estadistec.excepciones.ExcepcionLlaveExistente;
import estadistec.excepciones.ExcepcionLlaveInexistente;
import estadistec.excepciones.Excepcion;

/**
 * Gestor Principal. Clase inicial de la logica, es el nodo raiz. En el es 
 * donde se almacenan los escritorios.
 *
 * La ventana gráfica tiene una instancia del SuperGestor, así cada vez
 * que el usuario solicite agregar una tabla o algo desde el menú o la barra
 * de herramientas, se hace la solicitud al SuperGestor. El SuperGestor
 * "sabe" cuál es el escritorio que está activo, y agrega lo solicitado
 * a dicho escritorio.
 */
public class SuperGestor extends Gestor<LEscritorio>
{

	/**
	 * Instancia del singleton.
	 */
	private static SuperGestor instancia;

	/**
	 * Constructor del SuperGestor. Es privado, de manera que se llame
	 * solamente en caso de que la instancia no haya sido creada aún.
	 */
	private SuperGestor()
	{
		// Se llama al constructor del Gestor para que inicialice
		// la construcción de las llaves, e inicie el número de
		// los escritorios.
		super();
		this._manejables = new Hashtable<Long, LEscritorio>();
		_indNombre = 1;
	}

	/** 
	 * Método para ordenar las ventanas del escritorio actual. Se ordenan
	 * como cascada.
	 */
	public void ordenarCascada() {
		this._escritorioActual.ordenarCascada();
	}

	/** 
	 * Método para ordenar las ventanas del escritorio actual. Se ordenan
	 * como cuadrícula.
	 */
	public void ordenarCuadricula() {
		this._escritorioActual.ordenarCuadricula();
	}

	/** 
	 * Nombre requerido para asignar un nuevo nombre.
	 */
	protected String nombreManejable() {
		return ("Hoja");
	}

	/**
	 * Devuelve la instancia del singleton
	 * 
	 * @return Instancia del singleton.
	 */
	public static SuperGestor getInstancia()
	{
		if (instancia == null)
			instancia = new SuperGestor();

		return instancia;
	}

	/** 
	 * El escritorio que está al frente.
	 */
	private LEscritorio _escritorioActual;


	/** 
	 * Define el escritorio que está activo.
	 * 
	 * @param llave Identificador del escritorio.
	 *
	 * @throws ExcepcionLlaveInexistente En el caso de que la llave dada
	 * no corresponda a ningún escritorio.
	 *
	 * @todo Falta conectar con la parte gráfica, para que además envíe el
	 * escritorio "hacia adelante".
	 */
	public void setEscritorioActual (Long llave) 
		throws ExcepcionLlaveInexistente 
	{
		if (!this._manejables.containsKey(llave))
			throw new ExcepcionLlaveInexistente("SuperGestor -> setEscritorioActual");
		_escritorioActual = this._manejables.get(llave);
	}

	/**
	 * Añade un escritorio a la colección. Crea el escritorio nuevo, y lo
	 * define como el escritorio actual. 
	 * 
	 * @return El escritorio.
	 *
	 * @todo Falta conectar con la parte gráfica.
	 */
	public LEscritorio crearLEscritorio() 
	{
		// Obteniendo una llave nueva
		Long llave = getNuevaLlave();

		// creando el escritorio
		LEscritorio lEscritorio 
			= new LEscritorio(llave, nuevoNombreManejable());

		this.agregar(lEscritorio);
		this.setEscritorioActual(llave);
		
		return lEscritorio;
	}


	/** 
	 * Crea una tabla, según el tipo dado, en el escritorio que tiene
	 * como escritorio actual el SuperGestor.
	 */
	public void crearTabla(TipoTabla tipo) {
		_escritorioActual.crearTabla(tipo);
	}

	/** 
	 * Método que busca un nodo según una cadena de nombres. Dado
	 * que es el SuperGestor, deberíamos estar al final de la cadena.
	 * 
	 * @param nombres Nombres de los padres y Nodo.
	 * @param nivel Nivel actual en los nombres.
	 * 
	 * @return Nodo que se busca o {@code null} si no está.
	 */
	public Nodo buscarRaiz(String[] nombres, int nivel) {
		if (nivel > 0)
			return null;
		return (buscarNodo(nombres, nivel));
	}

	/** 
	 * Método que busca un nodo según una cadena de nombres. 
	 * 
	 * @param nombres Nombres de los padres y Nodo.
	 * @param nivel Nivel actual en los nombres.
	 * 
	 * @return Nodo que se busca o {@code null} si no está.
	 */
	public Nodo buscarNodo(String[] nombres, int nivel) {
		// Verificar que a la algura del SuperGestor el nivel es 0.
		assert (nivel == 0);

		// Escritorio donde es posible que se encuentre el Nodo.
		LEscritorio buscarEn = getManejableXNombre(nombres[nivel]);
		if (buscarEn == null)
			return null;
		return (buscarEn.buscarNodo(nombres, nivel + 1));
	}

}

